/////////////////////////////////////////////////////////////////////
//
//  Tackle - A Scrum Tracking Web Site Solution
//  Original Copyright ?2007 Microsoft Corp.  All rights reserved.
//  Released under Microsoft Permissive License (Ms-PL)
//  http://www.codeplex.com/Tackle/Project/License.aspx
//
/////////////////////////////////////////////////////////////////////

using System;
using System.Data;
using System.Configuration;

using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
using System.Web.Configuration;
using System.Text;


/// <summary>
/// Summary description for utility
/// </summary>
public static class TackleUtility
{
    // ***********************************************************************************
    // Throughout the site we need to keep track of the sprint we are currently working in
    // we'll provide some utility functions to do that while we move around
    private const string ckidSprintSelection = "Tackle_SprintSelection";
    public static void SaveSprintInCookie(DropDownList ddSprintSelection)
    {
        // save the cookie...
        if (ddSprintSelection.SelectedIndex != -1)
            SetCookieInfo(ckidSprintSelection, ddSprintSelection.SelectedValue);
    }

    public static void SetSprintFromCookie(DropDownList ddSprintSelection)
    {
        // grab the cookie value and set it if we have any sprints to select
        if (ddSprintSelection.Items.Count > 0)
        {
            // if a user switches scrum teams, the call to set the selected value is going to break
            // since the value is going to be for a different scrum team...
            try
            {
                // try to read it and set it...
                ListItem li = ddSprintSelection.Items.FindByValue(TackleUtility.GetCookieInfo(ckidSprintSelection, "0"));
                if (li == null)
                    ddSprintSelection.SelectedIndex = 0;
                else
                    ddSprintSelection.SelectedValue = li.Value;
            }
            catch (ArgumentOutOfRangeException)
            {
                // if we fail, select the first one
                ddSprintSelection.SelectedIndex = 0;
            }
            finally
            {
                // and then always, always save it
                SaveSprintInCookie(ddSprintSelection);
            }
        }
    }

    // **************************************************************************************


    // *******************
    public static void SetupFocusAllText(object sender)
    {
        // add an autoselect option on all actual, remaining and punted text boxes
        TextBox tb = (TextBox)sender;
        tb.Attributes.Add("onfocus", "this.select()");
    }

    public static bool SetEditControlFocus(ScriptManager sm, object sender, int nCell, int nControl)
    {
        // sets the focus to the control passed in
        try
        {
            GridView gv = (GridView)sender;
            if (gv.EditIndex != -1)
            {
                TextBox tb = ((TextBox)gv.Rows[gv.EditIndex].Cells[nCell].Controls[nControl]);
                if (tb != null)
                {
                    sm.SetFocus(tb);
                }
            }
        }
        catch (Exception)
        {
            return false;
        }

        return true;
    }

    public static bool SetEditControlFocus(ScriptManager sm, object sender, string ControlName)
    {
        // sets the focus to the control passed in
        try
        {
            GridView gv = (GridView)sender;
            if (gv.EditIndex != -1)
            {
                TextBox tb = ((TextBox)gv.Rows[gv.EditIndex].FindControl(ControlName));
                if (tb != null)
                {
                    sm.SetFocus(tb);
                }
            }
        }
        catch (Exception)
        {
            return false;
        }

        return true;
    }

    public static string GetPageNameFromURL(string url)
    {
        string page = url.Substring(url.LastIndexOf("/") + 1);
        if (page.IndexOf("?") >= 0)
        {
            page = page.Substring(0, page.IndexOf("?"));
        }
        return page;
    }

    // Turn the row associated with the specified ID into edit mode
    public static void SetRecordIntoEditMode(GridView gv, int IDtoSelect)
    {
        // now find the row to edit... hopefully it'll be near the top ("__New_Sprint__") :) 
        // since we can multipage, we have to go looking for the right page to edit too
        gv.DataBind(); // just make sure we have the latest data...
        bool bEditComplete = false;
        for (int pgcnt = 0; pgcnt < gv.PageCount && !bEditComplete; pgcnt++)
        {
            // rebind the new data
            gv.PageIndex = pgcnt;
            gv.DataBind();

            for (int gvr = 0; gvr < gv.Rows.Count; gvr++)
            {
                if (Convert.ToInt32(gv.DataKeys[gvr].Value) == IDtoSelect)
                {
                    // found it, get out then...
                    gv.EditIndex = gvr;
                    bEditComplete = true;   // get out of the outside loop
                    break;
                }
            }
        }
    }

    public static void MaxLength_ServerValidate(object source, ServerValidateEventArgs args)
    {
        // checks to see if the textbox contains text longer than a certain size and won't let
        // the user submit if it's longer than that.

        CustomValidator cv = (CustomValidator)source;
        int cntChars = Convert.ToInt32(cv.ToolTip);

        // now check the length
        if (args.Value.Length > cntChars)
        {
            args.IsValid = false;
        }
    }

    public static float ShowMasterBacklogInWeeks(string ScrumTeamID)
    {
        // Gets the display for weeks or hours on the product backlog as some teams
        // use hours instead of weeks for their masterbacklog. So now the db stores things
        // in hours and we'll manually do the conversions back and forth.
        SqlParameter[] sqlParams = new SqlParameter[] {
            new SqlParameter("@PrefValue", "MBInWeeks"),
            new SqlParameter("@ScrumTeamID", ScrumTeamID)
        };

        bool InWeeks = Convert.ToBoolean(TackleUtility.CallStoredProc("GetScrumTeamPreferenceValue", sqlParams, null, SProcReturnValue.ScalarValue));

        if (InWeeks)
            return 0.025f;  // 1 / 40 == 0.025f (use this to make hours into weeks)
        else
            return 1;       // otherwise just use 1 cause 1 hour is 1 hour
    }

    public static float ShowSprintBacklogInDays(string ScrumTeamID)
    {
        // Gets the display for weeks or hours on the product backlog as some teams
        // use hours instead of weeks for their masterbacklog. So now the db stores things
        // in hours and we'll manually do the conversions back and forth.
        SqlParameter[] sqlParams = new SqlParameter[] {
            new SqlParameter("@PrefValue", "SBInDays"),
            new SqlParameter("@ScrumTeamID", ScrumTeamID)
        };

        bool InDays = Convert.ToBoolean(TackleUtility.CallStoredProc("GetScrumTeamPreferenceValue", sqlParams, null, SProcReturnValue.ScalarValue));

        if (InDays)
            return 0.125f;  // 1 / 8 == 0.125f (use this to make hours into days)
        else
            return 1;       // otherwise just use 1 cause 1 hour is 1 hour
    }

    public static short GetTimeReportingDayForScrumTeam(string ScrumTeamID)
    {
        // Get the day of reporting time for the scrum team
        // open the connection
        SqlParameter[] sqlParams = new SqlParameter[] {
            new SqlParameter("@PrefValue", "TimeRepDay"),
            new SqlParameter("@ScrumTeamID", ScrumTeamID)
        };

        Int16 retVal = 0;
        retVal = Convert.ToInt16(TackleUtility.CallStoredProc("GetScrumTeamPreferenceValue", sqlParams, null, SProcReturnValue.ScalarValue));
        return retVal;

    }

    public static bool ConfirmDailyScrumTimeEntry(string ScrumTeamID)
    {
        // Get the state of whether the scrum team members are to 
        // update their task status after adding time
        SqlParameter[] sqlParams = new SqlParameter[] {
            new SqlParameter("@PrefValue", "ConfDSE"),
            new SqlParameter("@ScrumTeamID", ScrumTeamID)
        };

        bool retVal = false;
        retVal = Convert.ToBoolean(TackleUtility.CallStoredProc("GetScrumTeamPreferenceValue", sqlParams, null, SProcReturnValue.ScalarValue));
        return retVal;
    }

    public static bool DisableDailyTimeUserFilter(string ScrumTeamID)
    {
        // Get the state of whether the user filter on the DSE is to be disabled
        SqlParameter[] sqlParams = new SqlParameter[] {
            new SqlParameter("@PrefValue", "DSEFilter"),
            new SqlParameter("@ScrumTeamID", ScrumTeamID)
        };

        bool retVal = false;
        retVal = Convert.ToBoolean(TackleUtility.CallStoredProc("GetScrumTeamPreferenceValue", sqlParams, null, SProcReturnValue.ScalarValue));
        return retVal;
    }


    public static bool ShowTaskIDs(string ScrumTeamID)
    {
        // Get the state of whether the user filter on the DSE is to be disabled
        SqlParameter[] sqlParams = new SqlParameter[] {
            new SqlParameter("@PrefValue", "ShowTaskID"),
            new SqlParameter("@ScrumTeamID", ScrumTeamID)
        };

        bool retVal = false;
        retVal = Convert.ToBoolean(TackleUtility.CallStoredProc("GetScrumTeamPreferenceValue", sqlParams, null, SProcReturnValue.ScalarValue));
        return retVal;
    }

    public static bool ShowMBIDs(string ScrumTeamID)
    {
        // Get the state of whether the user filter on the DSE is to be disabled
        SqlParameter[] sqlParams = new SqlParameter[] {
            new SqlParameter("@PrefValue", "ShowMBID"),
            new SqlParameter("@ScrumTeamID", ScrumTeamID)
        };

        bool retVal = false;
        retVal = Convert.ToBoolean(TackleUtility.CallStoredProc("GetScrumTeamPreferenceValue", sqlParams, null, SProcReturnValue.ScalarValue));
        return retVal;
    }



    /// <summary>
    /// Gets information from "MS_Tackle" cookie. This is used for the pages to load some persistent settings (page size etc.)
    /// </summary>
    public static string GetCookieInfo(string cookieId, string defaultSetting)
    {
        HttpCookie cookie = HttpContext.Current.Request.Cookies["MS_Tackle"];

        if (cookie == null || cookie[cookieId] == null)
        {
            return defaultSetting;
        }
        return cookie[cookieId];
    }

    public static DateTime GetSprintStartDate(string SprintSelected)
    {
        // error handling
        if (string.IsNullOrEmpty(SprintSelected) || SprintSelected == null)
            return DateTime.Today;

        // Return the start date of the sprint so we can control the entry date
        // and not allow people to change values before the start date
        DateTime dt = DateTime.Today;

        SqlParameter[] sqlParams = new SqlParameter[] {
            new SqlParameter("@SprintID", SprintSelected)
        };

        // get the sprint start date
        object obj = TackleUtility.CallStoredProc("GetSprintStartDate", sqlParams, null, TackleUtility.SProcReturnValue.ScalarValue);
        if (obj != null)
            dt = (DateTime)obj;

        // return the date time or NULL
        return dt;
    }

    public static DateTime GetSprintEndDate(string SprintSelected)
    {
        // error handling
        if (string.IsNullOrEmpty(SprintSelected) || SprintSelected == null)
            return DateTime.Today;

        // Return the start date of the sprint so we can control the entry date
        // and not allow people to change values before the start date
        DateTime dt = DateTime.Today;

        SqlParameter[] sqlParams = new SqlParameter[] {
            new SqlParameter("@SprintID", SprintSelected)
        };

        // get the sprint start date
        object obj = TackleUtility.CallStoredProc("GetSprintEndDate", sqlParams, null, TackleUtility.SProcReturnValue.ScalarValue);
        if (obj != null)
            dt = (DateTime)obj;

        // return the date time or NULL
        return dt;
    }

    /// <summary>
    /// Gets information from "MS_Tackle" cookie. This is used for the pages to save some persistent settings (page size etc.)
    /// </summary>
    public static void SetCookieInfo(string cookieId, string setting)
    {
        try
        {
            HttpCookie cookie = HttpContext.Current.Response.Cookies["MS_Tackle"];
            HttpCookie reqCookie = HttpContext.Current.Request.Cookies["MS_Tackle"];

            foreach (string strKey in reqCookie.Values)
            {
                cookie[strKey] = reqCookie[strKey];
            }

            cookie[cookieId] = setting;
            cookie.Expires = DateTime.Now.AddYears(1);
        }
        catch (Exception)
        {
            // if the cookie fails to set, don't stop the app.
        };

    }

    /// <summary>
    /// Calls stored procedure with one parameter
    /// </summary>
    /// <param name="SProc"></param>
    /// <param name="ParamName"></param>
    /// <param name="ParamValue"></param>
    public static object CallStoredProc(string SProc, string ParamName, string ParamValue, GridView gv, SProcReturnValue spRetVal)
    {
        SqlParameter[] sqlParams = new SqlParameter[] { new SqlParameter(ParamName, ParamValue) };
        return CallStoredProc(SProc, sqlParams, gv, spRetVal);
    }

    public enum SProcReturnValue
    {
        RowsAffected = 0,
        ScalarValue = 1
    };

    public static object CallStoredProc(string SProc, SqlParameter[] sqlParams, GridView gv, SProcReturnValue spRetVal)
    {
        object iRc = 0;
        string ConnStr = WebConfigurationManager.ConnectionStrings["TackleConnectionStringMain"].ConnectionString;
        SqlConnection conn = new SqlConnection(ConnStr);

        try
        {
            // open the connection   
            conn.Open();

            // setup the command
            SqlCommand comm = new SqlCommand(SProc);
            comm.CommandType = CommandType.StoredProcedure;
            comm.Connection = conn;

            // setup the parameters
            if (sqlParams != null)
            {
                foreach (SqlParameter param in sqlParams)
                {
                    comm.Parameters.Add(param);
                }
            }

            // do we do rows affected or scalar
            if (spRetVal == SProcReturnValue.RowsAffected)
                iRc = comm.ExecuteNonQuery();
            else
                iRc = comm.ExecuteScalar();

            // Update GridView if provided.
            if (gv != null)
            {
                gv.DataBind();
            }
        }
        catch (Exception ex)
        {
            // if we get here, we are in trouble... 
            TackleError.HandleGenericException(ex);
        }
        finally
        {
            // close the connection if its not already
            if (conn.State == ConnectionState.Open)
                conn.Close();
        }

        // return either the rows affected or scalar value returned
        return iRc;
    }

    public static void SetupRowMouseOverHighlight(GridViewRowEventArgs e)
    {
        if (HttpContext.Current.Session["EnableRowHighlighting"] != null &&
            (bool)(HttpContext.Current.Session["EnableRowHighlighting"]))
        {
            // For each databound data row, setup mouse rollover and mouse roll off attributes
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                // regular rows
                if (e.Row.RowState == DataControlRowState.Normal)
                {
                    // mouse over
                    e.Row.Attributes.Add("onmouseover", "this.style.backgroundColor='#FFC080'");
                    // mouse out
                    e.Row.Attributes.Add("onmouseout", "this.style.backgroundColor='#E3EAEB'");
                }

                // alternate row color
                if (e.Row.RowState == DataControlRowState.Alternate)
                {
                    // mouse over
                    e.Row.Attributes.Add("onmouseover", "this.style.backgroundColor='#FFC080'");
                    // mouse out
                    e.Row.Attributes.Add("onmouseout", "this.style.backgroundColor='#FFFFFF'");
                }

                // edit row color
                if (e.Row.RowState == DataControlRowState.Edit)
                {
                    // mouse over
                    e.Row.Attributes.Add("onmouseover", "this.style.backgroundColor='#7C6F57'");
                    // mouse out
                    e.Row.Attributes.Add("onmouseout", "this.style.backgroundColor='#7C6F57'");
                }
            }
        }
    }

    public static void GetSprintStatusReportDays(DropDownList ddWeekInSprint, DropDownList ddSprintSelection)
    {
        // For week ending we want to get the start and end dates of the sprint
        // then walk through looking for the day specified as the end of the week. Check the last day of the sprint
        // because it's probably not an EOW so add that if it's not.
        const DayOfWeek dowEndOfWeek = DayOfWeek.Friday;

        // clear the previous list
        ddWeekInSprint.Items.Clear();

        // all of this then goes into the drop down for week in sprint
        DateTime dtSprintStart = TackleUtility.GetSprintStartDate(ddSprintSelection.SelectedValue);
        DateTime dtSprintEnd = TackleUtility.GetSprintEndDate(ddSprintSelection.SelectedValue);


        // now iterate back through the sprint so the drop down is in order from newest to oldest
        // we go 6 days past the end of the sprint to ensure we get the last EOW day on or after the sprint end
        for (DateTime dtDay = dtSprintEnd.AddDays(6); dtDay >= dtSprintStart; dtDay = dtDay.AddDays(-1))
        {
            // get the EndofWeek day into the list
            if (dtDay.DayOfWeek == dowEndOfWeek)
                ddWeekInSprint.Items.Add(dtDay.ToShortDateString());

        }

        // now remove all dates that are more than 7 days away from today
        for (int i = 0; i < ddWeekInSprint.Items.Count; i++)
        {
            if (Convert.ToDateTime(ddWeekInSprint.Items[i].Text) > DateTime.Today.AddDays(6))
            {
                ddWeekInSprint.Items.RemoveAt(i);
                i--;
            }
        }

        // always ensure we have one day in the week end to view work done
        if (ddWeekInSprint.Items.Count == 0)
        {
            // find the first EOW day in the sprint
            for (DateTime dtFirstEOW = dtSprintStart; dtFirstEOW <= dtSprintEnd; dtFirstEOW = dtFirstEOW.AddDays(1))
            {
                // get the day into the list
                if (dtFirstEOW.DayOfWeek == dowEndOfWeek)
                {
                    ddWeekInSprint.Items.Add(dtFirstEOW.ToShortDateString());
                    break;
                }
            }

            // if still no days, then there are no EOW days so use the sprint end date
            if (ddWeekInSprint.Items.Count == 0)
                ddWeekInSprint.Items.Add(dtSprintEnd.ToShortDateString());
        }
    }
    // delete all associated daily times
    public static void DeleteDailyTimeUpdates(int sbid)
    {
        // We need to remove the daily time updates for this task before
        // we attempt to delete the item

        SqlParameter[] sqlParams = new SqlParameter[] {
                new SqlParameter("@SprintBacklogID", sbid)
            };

        // delete any associated daily time updates
        CallStoredProc("DeleteDailyTimeUpdates", sqlParams, null, SProcReturnValue.RowsAffected);

    }
}

/// <summary>
/// Class is used to standardize code across edit sprint backlog and daily scrum entry pages
/// </summary>
public class SprintBacklogSharedCode
{
    protected enum SprintTaskType { All = -3, OOF = -2, Discovered = -1 };

    public bool SetEditRowIndex(object sender, object IDtoEdit)
    {
        // called when each of the grid views are databound
        // we check the viewstate to see if we should be editing
        // a particular record. If we are, we find it and edit it.

        try
        {
            if (IDtoEdit != null)
            {
                int SPID = Convert.ToInt32(IDtoEdit);
                // select the row to edit...
                GridView gv = (GridView)sender;
                for (int i = 0; i < gv.Rows.Count; i++)
                {
                    if (Convert.ToInt32(gv.DataKeys[i].Value) == SPID)
                    {
                        gv.EditIndex = i;
                        return true;    // indicate we've find the item to edit.
                    }
                }
            }
        }
        catch (Exception)
        {
            return false;
        }

        return false;   // we didn't find the row to edit
    }

    public int InsertItemToSprintProc(int MasterBacklogID, string SprintID, float RemainTime, bool bSplitDescToTasks, int ScrumTeamID, bool bDiscovered)
    {
        //
        // Inserts a new items into the sprint backlog from the edit sprint backlog or daily scrum entry page
        //

        SqlParameter[] sqlParams = new SqlParameter[] {
            new SqlParameter("@MasterBacklogID", MasterBacklogID),
            new SqlParameter("@SprintID", SprintID),
            new SqlParameter("@OOF", false),
            new SqlParameter("@Unbuffered", false),
            new SqlParameter("@Discovered", bDiscovered),
            new SqlParameter("@RemainingTime", RemainTime),
            new SqlParameter("@SplitDescToTasks", bSplitDescToTasks),
            new SqlParameter("@ScrumTeamID", ScrumTeamID),
        };


        // OOF? If a task is OOF, it's also unbuffered
        if (MasterBacklogID == Convert.ToInt32(SprintTaskType.OOF))
        {
            sqlParams[2].Value = true; // OOF
            sqlParams[3].Value = true; // Unbuffered
        }

        // Discovered? 
        if (MasterBacklogID == Convert.ToInt32(SprintTaskType.Discovered))
            sqlParams[4].Value = true; // Discovered

        // call the sproc
        return Convert.ToInt32(TackleUtility.CallStoredProc("InsertItemIntoSprint",
            sqlParams, null, TackleUtility.SProcReturnValue.ScalarValue));

    }

    public void UpdateOwnerForTask(string TaskOwnerID, string SprintBacklogID)
    {
        //
        // Updates the taskownerid for the sprintbacklogid passed in
        //

        SqlParameter[] sqlParams = new SqlParameter[] {
            new SqlParameter("@TaskOwnerID", TaskOwnerID),
            new SqlParameter("@SprintBacklogID", SprintBacklogID)
        };

        TackleUtility.CallStoredProc("UpdateOwnerForTask",
                sqlParams, null, TackleUtility.SProcReturnValue.RowsAffected);
    }
}

public class SprintTotalsProcessRow
{
    protected float SumBaseline;
    protected float SumActualWork;
    protected float SumRemainWork;
    protected float SumRemainOOF;
    protected float SumHoursRemain;
    protected float SumAheadBehind;
    protected float SumPunted;
    protected float SumActualOOF;
    protected float SumPlannedWork;
    protected float SumDiscoveredWork;
    protected float AvgPlannedDiscBuffer;
    protected float AvgBuffer;
    protected int RowCount;

    public void ProcessRow(GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            // do our summing
            SumBaseline += GetDataItemValue(e, "BaseLineHours");
            SumActualWork += GetDataItemValue(e, "ActualWorkComp");
            SumRemainWork += GetDataItemValue(e, "RemainingWork");
            SumRemainOOF += GetDataItemValue(e, "RemainingOOF");
            SumHoursRemain += GetDataItemValue(e, "AvailHoursRemaining");
            SumAheadBehind += GetDataItemValue(e, "AheadBehindOnWork");
            SumPunted += GetDataItemValue(e, "PuntedWork");
            SumActualOOF += GetDataItemValue(e, "ActualOOF");
            SumPlannedWork += GetDataItemValue(e, "PlannedWorkComp");
            SumDiscoveredWork += GetDataItemValue(e, "DiscoveredWork");
            AvgPlannedDiscBuffer += GetDataItemValue(e, "PlannedDiscBuffer");
            AvgBuffer += GetDataItemValue(e, "ActualBuffer");
            RowCount++;
        }

        if (e.Row.RowType == DataControlRowType.Footer)
        {
            // output things
            e.Row.Cells[0].Text = "Total";
            e.Row.Cells[4].Text = RoundVal(SumBaseline);
            e.Row.Cells[6].Text = RoundVal(SumActualWork);
            e.Row.Cells[7].Text = RoundVal(SumRemainWork);
            e.Row.Cells[8].Text = RoundVal(SumRemainOOF);
            e.Row.Cells[9].Text = RoundVal(SumHoursRemain);
            e.Row.Cells[10].Text = RoundVal(SumAheadBehind);
            e.Row.Cells[11].Text = RoundVal(SumPunted) + " (" + RoundVal((SumPunted / SumBaseline) * 100) + "%)";
            e.Row.Cells[12].Text = RoundVal(SumActualOOF);
            e.Row.Cells[13].Text = RoundVal(SumPlannedWork);
            e.Row.Cells[14].Text = RoundVal(SumDiscoveredWork);
            e.Row.Cells[15].Text = RoundVal(AvgPlannedDiscBuffer / RowCount);
            e.Row.Cells[16].Text = RoundVal(AvgBuffer / RowCount);
        }
    }

    protected float GetDataItemValue(GridViewRowEventArgs e, string DataText)
    {
        return Convert.ToSingle(DataBinder.Eval(e.Row.DataItem, DataText));
    }

    protected string RoundVal(float num)
    {
        try
        {
            if (float.IsNaN(num))
                return "0.00";

            double f = Math.Round(num, 2);
            return f.ToString("F");
        }
        catch
        {
            return "N/A";
        }
    }

}

public static class TackleError
{
    public enum ErrorCode
    {
        NoError = 0,
        Unknown,
        SiteAccessDenied,
        PageAccessDenied,
        SessionTimeOut,
        CustomErrorMessage,
    };

    public static void SiteAccessDenied()
    {
        HttpContext.Current.Response.Redirect("Error.aspx?ErrorCode=" + ((int)ErrorCode.SiteAccessDenied).ToString());
    }

    public static void PageAccessDenied()
    {
        HttpContext.Current.Response.Redirect("Error.aspx?ErrorCode=" + ((int)ErrorCode.PageAccessDenied).ToString());
    }

    public static void SessionTimeOut()
    {
        HttpContext.Current.Response.Redirect("Error.aspx?ErrorCode=" + ((int)ErrorCode.SessionTimeOut).ToString());
    }

    public static void HandleGenericException(Exception ex)
    {
        if (ex is SqlException)
        {
            // try to give bit better information than ex.ToString()
            SqlException sqlex = (SqlException)ex;
            StringBuilder sb = new StringBuilder();
            sb.Append(String.Format("ErrorCode: {0:x}\r\n", sqlex.ErrorCode));
            foreach (SqlError err in sqlex.Errors)
            {
                if (err.Procedure != null && err.Procedure.Length != 0)
                {
                    sb.Append(String.Format("{0} :line {1}: : ", err.Procedure, err.LineNumber));
                }
                sb.Append(String.Format("ErrorNumber {0}: {1}\r\n", err.Number, err.Message));
            }
            sb.Append(sqlex.StackTrace);
            CustomErrorMessage(sb.ToString());
        }
        else
        {
            CustomErrorMessage(ex.ToString());
        }
    }

    public static void CustomErrorMessage(string info)
    {
        HttpContext.Current.Session.Add("ErrorInfo", info);
        HttpContext.Current.Response.Redirect("Error.aspx?ErrorCode=" + ((int)ErrorCode.CustomErrorMessage).ToString());
    }
}